home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 038a / qbtree45.zip / QBTREE45.DOC < prev    next >
Text File  |  1991-01-03  |  53KB  |  2,971 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.                                 A B-Tree Access Method
  17.                              for QuickBASIC Programmers.
  18.  
  19.  
  20.  
  21.                                     QBTREE v4.50 
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.                                      Jan 3, 1991
  29.                                (C)1989-1991 Cornel Huth
  30.  
  31.  
  32.  
  33.           The QBTREE package is a shareware product. You may try QBTREE to
  34.           see if it fits your needs on a trial basis only. You may copy and
  35.           distribute this shareware package freely. If you plan to use it
  36.           after the trial, fill out the registration form and send it along
  37.           with payment of $45 to:
  38.  
  39.                Cornel Huth
  40.                ATTN: QBTREE 4.50 REGISTRATION
  41.                6402 Ingram Rd.
  42.                San Antonio, TX  78238
  43.  
  44.           Source code for the QBTREE interface will be sent upon receipt of
  45.           the completed registration form on the last page. This interface
  46.           is all that is needed to modify QBTREE for most situations since
  47.           all I/O is performed at this level (QuickBASIC). If you also need
  48.           the low-level btree routine, I'll make it available. It's written
  49.           in MASM assembly. (Contact me for more details.)
  50.  
  51.           QBTREE requires QuickBASIC 4.00 or above. For file sharing and
  52.           record locking functions DOS 3.0 or above is needed.
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.           WHAT IS IT?
  74.  
  75.           QBTREE is a keyed-file system based on the b-tree sorting method.
  76.           It maintains up to 5 key files and also 5 data files at one time.
  77.           (Source is available to modify this to your needs; DOS 3.30 and
  78.           up allow you to use as many as 255 total files.) Not only does
  79.           QBTREE find any particular key and its data record very quickly 
  80.            - any key from a million-key file in 1/10 second on a 18ms hard
  81.           disk (worst-case) - it also allows sequential inorder access to
  82.           the data file. The data file is automatically maintained and the
  83.           index file automatically balanced. Deletions in both the data and
  84.           key files are made available for reuse, thus making repacking
  85.           unnecessary.
  86.  
  87.           The following files should be found in this shareware package:
  88.  
  89.                QBTREE45.LIB   standard btree library
  90.                NBTREE45.LIB   network btree library
  91.                QBTREE45.BI    btree routine function prototypes
  92.                TEST45.BAS     barebones btree program using most routines
  93.                MEMCOPY.ASM    assembly source for the MEMCOPY routine
  94.                QBTREE45.DOC   this documentation
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.           INSTALLATION
  140.  
  141.  
  142.           Add QBTREE45.LIB to your standard library if you like, and then  
  143.           LINK /QU it into a QLB library for the environment.
  144.  
  145.                C>lib yourstd.lib + QBTREE45.LIB;
  146.  
  147.                C>link /qu yourstd.lib,qb.qlb,nul,bqlb4x.lib
  148.  
  149.           You may prefer to keep QBTREE45.LIB as a separate library,
  150.           instead.
  151.  
  152.                C>link /qu yourstd.lib+QBTREE45.LIB,qb.qlb,nul,bqlb4x.lib
  153.  
  154.           Don't forget to invoke QB with the /l libraryname parameter.
  155.  
  156.           QBTREE comes as two separate libraries. One for standard
  157.           applications, the other for network applications. If you need the
  158.           network support routines, substitute NBTREE45.LIB for
  159.           QBTREE45.LIB.
  160.  
  161.           Note that INTERRUPT and INTERRUPTX are defined in the module     
  162.           INTRPT within the QBTREE45 library. If you prefer to not have it
  163.           there but instead in your own library, remove it from
  164.           QBTREE45.LIB, e.g.,
  165.  
  166.                C>lib QBTREE45.LIB -INTRPT;
  167.  
  168.           Otherwise, you may see a linker error about INTERRUPT and
  169.           INTERRUPTX having already been defined. If you would rather not
  170.           see these messages add the /NOE option to link. Note that QB
  171.           4.00b, and 4.50 have a bug in the interrupt code when doing
  172.           interrupts 25/26h. QB 4.00 has this bug and another that causes
  173.           the passed di register to not be properly passed. I recommend
  174.           that if you use INTERRUPT(X) that you replace you INTRPT code
  175.           with the INTRPT code included with QBTREE45 whether you intend to
  176.           use QBTREE or not. To do that:
  177.  
  178.                C>lib QBTREE45 *INTRPT;  {first make a copy of it}
  179.                C>lib QB.LIB -+INTRPT;   {then replace bad with good}
  180.                C>link /qu QB.LIB...     {and make a new QLB}  
  181.                  
  182.           When linking a stand-alone program include the library in the
  183.           link process by adding QBTREE45.LIB to the libraries prompt from
  184.           LINK.EXE. If you are using a compiler other than BC 4.00b, LINK
  185.           will ask for the path to BCOM41.LIB. For the shareware evaluation
  186.           you can enter the path to your run-time library. If you are using
  187.           BC 4.00 the name is \path\BCOM40.LIB. If you are using BC 4.5 the
  188.           name is \path\BCOM45.LIB. With registration you receive the
  189.           source, ready to be compiled by your compiler version. Thereafter
  190.           LINK won't prompt you for the run-time library path.
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.           INTERFACE SUMMARY
  206.  
  207.  
  208.           All QBTREE routines are FUNCTIONs and return an integer code     
  209.           which is detailed in ERROR CODES. These must be DECLAREd.
  210.           Use REM $INCLUDE:"QBTREE45.BI" in your programs.
  211.  
  212.            1) AddRecord% (kfile%, dfile%, Qkey$, Qrec$)
  213.            2) CloseDataFile% (dfileno%)
  214.            3) CloseKeyFile% (kfileno%)
  215.            4) CreateDataFile% (filename$, recl%)
  216.            5) CreateKeyFile% (filename$, keyl%)
  217.            6) DeleteKey% (kfile%, Qkey$)
  218.            7) DeleteRecord% (kfile%, dfile%, Qkey$)
  219.            8) FlushDataFile% (dfileno%, dup%)
  220.            9) FlushKeyFile% (kfileno%, dup%)
  221.           10) GetDirect% (dfileno%, recno&, Qrec$)
  222.           11) GetEqual% (kfile%, dfile%, Qkey$, Qrec$)
  223.           12) GetFirst% (kfile%, dfile%, Qkey$, Qrec$)
  224.           13) GetLast% (kfile%, dfile%, Qkey$, Qrec$)
  225.           14) GetNext% (kfile%, dfile%, Qkey$, Qrec$)
  226.           15) GetPosition% (kfileno%, recno&)
  227.           16) GetPrev% (kfile%, dfile%, Qkey$, Qrec$)
  228.           17) OpenDataFile% (filename$, dfileno%)
  229.           18) OpenKeyFile% (filename$, kfileno%)
  230.           19) PutKey% (kfile%, dfile%, Qkey$)
  231.           20) QBTreeVer% (ver%)
  232.           21) StatDataFile% (dfileno%, recl%, recs&, bfileno%)
  233.           22) StatKeyFile% (kfileno%, keyl%, keys&, bfileno%)
  234.           23) UpdateRecord% (dfile%, Qrec$)
  235.  
  236.  
  237.           These are network support routines available in NBTREE45.LIB.
  238.  
  239.           24) LoadDataHeader% (dfileno%)
  240.           25) LoadKeyHeader% (kfileno%)
  241.           26) LockDataHeader% (dfileno%)
  242.           27) LockKeyFile% (kfileno%)
  243.           28) LockRecord% (dfileno%, recno&)
  244.           29) UnlockDataHeader% (dfileno%)
  245.           30) UnlockKeyFile% (kfileno%) 
  246.           31) UnlockRecord% (dfileno%, recno&)
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.           INTERFACE DETAIL
  272.  
  273.  
  274.            1) AddRecord(kfile,dfile,Qkey$,Qrec$)
  275.  
  276.           Add the key, Qkey$, to the key file, kfile, and the data record,
  277.           Qrec$, to the data file, dfile. Qkey$ must not already exist.
  278.           QBTREE is case-sensitive so it is recommended that keys be made
  279.           upper-case (or lower) unless there is a reason not to do this.
  280.  
  281.           kfile          INTEGER.  Number that was used as fileno in
  282.                          OpenKeyFile().
  283.  
  284.           dfile          INTEGER.  Number that was used as fileno in
  285.                          OpenDataFile().
  286.  
  287.           Qkey$          STRING.   Key to add to key file.
  288.  
  289.           Qrec$          STRING.   Data record to add to the data file
  290.                          indexed by Qkey$.
  291.  
  292.           DEFINT A-Z
  293.           kfile = 0
  294.           dfile = 0
  295.           Qkey$ = acctid$ + acctxn$
  296.           Qrec$ = xaction$
  297.           stat = AddRecord(kfile,dfile,Qkey$,Qrec$)
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.            2) CloseDataFile(dfile)
  338.  
  339.           Close the data file, dfile, releasing the data buffer allocated
  340.           to it. This function is essential for proper termination in
  341.           QBTREE. Release any active locks first.
  342.  
  343.           dfile          INTEGER.  Number that was used as fileno in
  344.                          OpenDataFile().
  345.  
  346.           dfile = 0
  347.           stat = CloseDataFile(dfile)
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.            3) CloseKeyFile(kfile)
  404.  
  405.           Close the key file, kfile. This is essential for proper
  406.           termination in QBTREE. Header information is written only when
  407.           the file is closed, or flushed. Release any active locks first.
  408.  
  409.           kfile          INTEGER.  Number that was used as fileno in
  410.                          OpenKeyFile().
  411.  
  412.           kfile = 0
  413.           stat = CloseKeyFile(kfile)
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.            4) CreateDataFile(filename$,reclen)
  470.  
  471.           Create a new data file. filename$ must not already exist.
  472.  
  473.           filename$      STRING.   Pathname of data file to create. Any
  474.                          valid DOS drive/path/filename can be used.
  475.                
  476.           reclen         INTEGER.  Length of record for this data file.
  477.                          Valid range is 3 to 32767 bytes, though QB's
  478.                          string space will be the limiting factor.
  479.  
  480.           filename$ = "C:\HIST\AR89.DAT"
  481.           reclen = 128
  482.           stat = CreateDataFile(filename$,reclen)
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.            5) CreateKeyFile(filename$,keylen)
  536.  
  537.           Create a new key file. filename$ must not already exist.
  538.  
  539.           filename$      STRING.   Pathname of key file to create. Any
  540.                          valid DOS drive/path/filename can be used.
  541.  
  542.           keylen         INTEGER.  Length of key for this key file. Valid
  543.                          range is 1 to 64 bytes.
  544.  
  545.           filename$ = "C:\HIST\AR89.KEY"
  546.           keylen = 16
  547.           stat = CreateKeyFile(filename$,keylen)
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.            6) DeleteKey(kfile,Qkey$)
  602.  
  603.           Delete the key, Qkey$, from kfile. The data record associated
  604.           with Qkey$ is not affected. This is necessary since you may have
  605.           other indexes pointing to the data record.
  606.  
  607.           kfile          INTEGER.  Number that was used as fileno in
  608.                          OpenKeyFile().
  609.  
  610.           Qkey$          STRING.   Key to remove from kfile.
  611.  
  612.           kfile = 0
  613.           Qkey$ = acctid$ + acctxn$
  614.           stat = DeleteKey(kfile,Qkey$)
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624.  
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.            7) DeleteRecord(kfile,dfile,Qkey$)
  668.  
  669.           Delete the key, Qkey$, from file kfile and also delete the
  670.           associated record from dfile.
  671.  
  672.           This function deletes Qkey$ only in kfile and also delete the
  673.           data record that Qkey$ had pointed to in dfile. If you have other
  674.           indexes pointing to this data record, use DeleteKey() on those
  675.           indexes before doing this function.
  676.  
  677.           kfile          INTEGER.  Number that was used as fileno in
  678.                          OpenKeyFile().
  679.  
  680.           dfile          INTEGER.  Number that was used as fileno in
  681.                          OpenDataFile().
  682.  
  683.           Qkey$          STRING.   Key for which you want to delete from   
  684.                          the key file, kfile, and also delete its
  685.                          associated data record in dfile.
  686.  
  687.           kfile = 0
  688.           dfile = 0
  689.           Qkey$ = acctid$ + acctxn$
  690.           stat = DeleteRecord(kfile,dfile,Qkey$)
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.            8) FlushDataFile(dfile,dup)
  734.  
  735.           Updates the data header information and, if dup is non-zero,
  736.           causes DOS to update the directory entry for dfile. This is done
  737.           by writing the data header out, having DOS duplicate dfile's
  738.           handle, then closing the duplicate handle. This does not have the
  739.           overhead of having to re-open the data file. This also flushes
  740.           DOS's internal buffers.
  741.  
  742.           In LAN applications you should perform this function before
  743.           releasing a data record lock, but dup must be equal to 0. If you
  744.           force DOS to update the directory entry, UnlockRecord() returns
  745.           error 229 - Lock already in force. Not flushing the buffers is
  746.           not a problem in LAN applications since the SHARE.EXE will not
  747.           allow 'local buffer' problems to occur.
  748.  
  749.           dfile          INTEGER.  Number that was used as fileno in
  750.                          OpenDataFile().
  751.  
  752.           dup            INTEGER.  Non-zero to force directory update.
  753.  
  754.           dfile = 0
  755.           dup = -1           'dup must be 0 for LAN applications
  756.           stat = FlushDataFile(dfile,dup)
  757.  
  758.           Note:  Flushing buffers should be done whenever processing can
  759.           handle the delay. Once a file has been flushed (and no further
  760.           changes have been made), a power-outage can bring your system
  761.           down with no ill-effects to the QBTREE file - all will be intact.
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.            9) FlushKeyFile(kfile,dup)
  800.  
  801.           Updates the key header information and, if dup is non-zero,
  802.           causes DOS to update the directory entry for kfile. This is done
  803.           by writing the key header out, having DOS duplicate file's
  804.           handle, then closing the duplicate handle. This does not have the
  805.           overhead of having to re-open the key file. This also flushes
  806.           DOS's internal buffers.
  807.  
  808.           In LAN applications you should perform this function before
  809.           releasing a key file lock, but dup must be equal to 0. If you
  810.           force DOS to update the directory entry, UnlockKeyFile() returns
  811.           error 229 - Lock already in force. Not flushing the buffers is
  812.           not a problem in LAN applications since the SHARE.EXE will not
  813.           allow 'local buffer' problems to occur.
  814.  
  815.           kfile          INTEGER.  Number that was used as fileno in
  816.                          OpenKeyFile().
  817.  
  818.           dup            INTEGER.  Non-zero to force directory update.
  819.  
  820.           kfile = 0
  821.           dup = -1           'dup must be 0 for LAN applications
  822.           stat = FlushKeyFile(kfile,dup)
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.           10) GetDirect(dfile,recno&,Qrec$)
  866.  
  867.           Return the data in dfile at the logical record number, recno&.
  868.           This is especially useful for reindexing data files, provided
  869.           that the key is imbedded in the data record. It is possible to
  870.           retrieve deleted records from the data file; records are not
  871.           physically deleted but are marked 'available' for a new data
  872.           record. See the data record format below. It is also possible to
  873.           give recno& a value past the true end of file. This function does
  874.           not affect the index file's internal pointers.
  875.  
  876.           dfile          INTEGER.  Number that was used as fileno in
  877.                          OpenDataFile().
  878.  
  879.           recno&         LONG.     Record number to seek (1-based).
  880.  
  881.           Qrec$          STRING.   Returned record data.
  882.  
  883.           dfile = 0
  884.           recno& = 456&
  885.           stat = GetDirect(dfile,recno&,Qrec$)
  886.           if stat = 0 then
  887.              print "Record#";recno&;" =";Qrec$
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.           11) GetEqual(kfile,dfile,Qkey$,Qrec$)
  932.  
  933.           Search for key, Qkey$, in kfile, and if found, retrieve the data
  934.           record from dfile, and place it in Qrec$. If not found, the
  935.           internal pointers indicate where it would have been. By using
  936.           GetNext(), GetPrev(), the next or previous ordered key and data
  937.           can be obtained.
  938.  
  939.           kfile          INTEGER.  Number that was used as fileno in
  940.                          OpenKeyFile().
  941.  
  942.           dfile          INTEGER.  Number that was used as fileno in
  943.                          OpenDataFile().
  944.  
  945.           Qkey$          STRING.   Key for which to search in key file.
  946.  
  947.           Qrec$          STRING.   Returned data record associated with
  948.                          Qkey$.
  949.  
  950.           kfile = 0
  951.           dfile = 0
  952.           Qkey$ = acctid$ + acctxn$
  953.           stat = GetEqual(kfile,dfile,Qkey$,Qrec$)
  954.                  '{Qrec$ is read}
  955.           if stat = 200 then
  956.              stat = GetNext(kfile,dfile,Qkey$,Qrec$)
  957.                    '{Qkey$ & Qrec$ are read}
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.  
  997.           12) GetFirst(kfile,dfile,Qkey$,Qrec$)
  998.  
  999.           Retrieve the first ordered key in kfile, placing it in Qkey$, and
  1000.           place its data record from dfile into Qrec$.
  1001.  
  1002.           kfile          INTEGER.  Number that was used as fileno in
  1003.                          OpenKeyFile().
  1004.  
  1005.           dfile          INTEGER.  Number that was used as fileno in
  1006.                          OpenDataFile().
  1007.  
  1008.           Qkey$          STRING.   Returned first ordered key.
  1009.  
  1010.           Qrec$          STRING.   Returned data record associated with
  1011.                          returned key, Qkey$.
  1012.  
  1013.           kfile = 0
  1014.           dfile = 0
  1015.           stat = GetFirst(kfile,dfile,Qkey$,Qrec$)
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.           13) GetLast(kfile,dfile,Qkey$,Qrec$)
  1064.  
  1065.           Retrieve the last ordered key in kfile, placing it in Qkey$, and
  1066.           place its data record from dfile into Qrec$.
  1067.  
  1068.           kfile          INTEGER.  Number that was used as fileno in
  1069.                          OpenKeyFile().
  1070.  
  1071.           dfile          INTEGER.  Number that was used as fileno in
  1072.                          OpenDataFile().
  1073.  
  1074.           Qkey$          STRING.   Returned last ordered key.
  1075.  
  1076.           Qrec$          STRING.   Returned data record associated with
  1077.                          returned key, Qkey$.
  1078.  
  1079.           kfile = 0
  1080.           dfile = 0
  1081.           stat = GetLast(kfile,dfile,Qkey$,Qrec$)
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.           14) GetNext(kfile,dfile,Qkey$,Qrec$)
  1130.  
  1131.           Retrieve the next ordered key in kfile, placing it in Qkey$, and
  1132.           place its data record from dfile into Qrec$. This function allows
  1133.           for sequential inorder processing of the data file.
  1134.  
  1135.           kfile          INTEGER.  Number that was used as fileno in
  1136.                          OpenKeyFile().
  1137.  
  1138.           dfile          INTEGER.  Number that was used as fileno in
  1139.                          OpenDataFile().
  1140.  
  1141.           Qkey$          STRING.   Returned key which immediately follows
  1142.                          the key found (or not found) in GetEqual() or
  1143.                          GetFirst().
  1144.  
  1145.           Qrec$          STRING.   Returned data record associated with
  1146.                          returned key, Qkey$.
  1147.  
  1148.           kfile = 0
  1149.           dfile = 0
  1150.           Qkey$ = acctid$ + acctxn$
  1151.           stat = GetNext(kfile,dfile,Qkey$,Qrec$)
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194.  
  1195.           15) GetPosition(kfile,recno&)
  1196.  
  1197.           Return the logical record number of the current record pointed to
  1198.           by the last key FOUND in kfile. This function can be used to
  1199.           match keys from different key files that relate to a data file by
  1200.           recno& only. (Useful in deleting non-relational keys.)
  1201.  
  1202.           kfile          INTEGER.  Number that was used as fileno in
  1203.                          OpenKeyFile().
  1204.  
  1205.           recno&         LONG.     Returned current record number in the
  1206.                          last used (current) data file.
  1207.  
  1208.           kfile = 0
  1209.           stat = GetPosition(kfile,recno&)
  1210.           if stat = 0 then
  1211.              print "Current data record of kfile";kfile;" is";recno&
  1212.  
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.           16) GetPrev(kfile,dfile,Qkey$,Qrec$)
  1262.  
  1263.           Retrieve the previous ordered key in kfile, placing it in Qkey$,
  1264.           and place its data record from dfile into Qrec$. This function
  1265.           allows for reverse sequential inorder processing of the data
  1266.           file.
  1267.  
  1268.           kfile          INTEGER.  Number that was used as fileno in
  1269.                          OpenKeyFile().
  1270.  
  1271.           dfile          INTEGER.  Number that was used as fileno in
  1272.                          OpenDataFile().
  1273.  
  1274.           Qkey$          STRING.   Returned key which immediately precedes
  1275.                          the key found (or not found) in GetEqual() or
  1276.                          GetLast().
  1277.  
  1278.           Qrec$          STRING.   Returned data record associated with
  1279.                          returned key, Qkey$.
  1280.  
  1281.           kfile = 0
  1282.           dfile = 0
  1283.           Qkey$ = acctid$ + acctxn$
  1284.           stat = GetPrev(kfile,dfile,Qkey$,Qrec$)
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327.           17) OpenDataFile(filename$,fileno)
  1328.  
  1329.           Open an EXISTING data file and associate it with fileno and
  1330.           allocate a data buffer the size of the datafile's record length.
  1331.  
  1332.           The fileno is a number you choose between 0 to 4. This number is
  1333.           used to reference the data file in any later operation. The
  1334.           maximum files can be increased or decreased by changing the MDF
  1335.           constant in the interface source.
  1336.  
  1337.           If version 3.0 or greater of DOS is detected by QBTREE then the
  1338.           open is performed with a READ/WRITE access and DENY NONE sharing.
  1339.           Older versions of DOS will have a normal open call (COMPATIBLE).
  1340.           What this means is that other processes may read from and write
  1341.           to the data file, filename$. See the LockRecord() and
  1342.           UnlockRecord() functions for details on locking the data file.
  1343.  
  1344.           filename$      STRING.   Pathname of existing data file.
  1345.  
  1346.           fileno         INTEGER.  Number to associate the data file with
  1347.                          for future operations. Valid range is 0 to 4.
  1348.  
  1349.           {See OpenKeyFile() for an example.}
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393.           18) OpenKeyFile(filename$,fileno)
  1394.  
  1395.           Open an EXISTING key file and associate it with fileno. Before
  1396.           *USING* the key file, a data file will also need to be opened.
  1397.           You may have multiple index files opened for a data file.
  1398.  
  1399.           The fileno is a number you choose between 0 to 4. This number is
  1400.           used to reference the key file in any later operation. The
  1401.           maximum files can be increased or decreased by changing the MKF
  1402.           constant in the interface source.
  1403.  
  1404.           If version 3.0 or greater of DOS is detected by QBTREE then the
  1405.           open is performed with a READ/WRITE access and DENY NONE sharing.
  1406.           Older versions of DOS will have a normal open call (COMPATIBLE).
  1407.           What this means is that other processes may read from and write
  1408.           to the key file, filename$. See the LockKeyFile() and
  1409.           UnlockKeyFile() functions for details on locking the key file.
  1410.  
  1411.           filename$      STRING.   Pathname of existing key file.   
  1412.  
  1413.           fileno         INTEGER.  Number to associate the key file with
  1414.                          for future operations. Valid range is 0 to 4.
  1415.  
  1416.           filename$ = "C:\HIST\AR89."
  1417.           ARKEY = 0
  1418.           ARDAT = 0
  1419.           stat = OpenKeyFile(filename$+"KEY",ARKEY)
  1420.           if stat = 0 then stat =  OpenDataFile(filename$+"DAT",ARDAT)
  1421.           if stat <> 0 then DoErrorProc stat
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.           19) PutKey(kfile,dfile,Qkey$)
  1460.  
  1461.           After having found a key with GetFirst(), GetLast(), GetPrev(),
  1462.           GetEqual(), GetNext(), or AddRecord(), insert the key Qkey$ into
  1463.           the key file, kfile (which most likely is an index file other
  1464.           than the one where the key was found, though it can be the same).
  1465.           Associated with it the data record that was indexed by the found
  1466.           key. This allows you have multiple indexes per data file. If an
  1467.           error code is returned you must *REACCESS* the original key (with
  1468.           the GETx()) before attempting to re-PutKey() error 206, invalid
  1469.           data pointer, is returned. If error 201, key already exists, is
  1470.           returned, and you want to allow duplicate keys, you need to add
  1471.           an enumerator to the key. See NON-UNIQUE KEYS below.
  1472.  
  1473.           kfile          INTEGER.  Number that was used as fileno in
  1474.                          OpenKeyFile().
  1475.  
  1476.           dfile          INTEGER.  Number that was used as fileno in
  1477.                          OpenDataFile().
  1478.  
  1479.           Qkey$          STRING.   Key for which you want to add to the key
  1480.                          file, kfile, and have it also point to the data
  1481.                          record in dfile whose key was last found.
  1482.  
  1483.           stat = GetEqual(0,0,Qkey$,Qrec$)
  1484.           if stat = 0 then
  1485.              enum = 0
  1486.              enum$ = mki$(enum)      'make it a string
  1487.              'need to reverse enum$ bytes to sort low to high
  1488.              'use a function in your code such as SwapByte$(),etc
  1489.              ZKey$ = NewKey$ + right$(enum$,1) + left$(enum$,1)
  1490.              stat = PutKey(1,0,ZKey$)
  1491.           else
  1492.              stop
  1493.           endif
  1494.           if stat = 201 then  'PutKey() key exists error
  1495.              'reset the internal pointer to a valid record
  1496.              stat = GetEqual(0,0,Qkey$,Qrec$)
  1497.              'look for the absolute last one (won't be found=200)
  1498.              stat = GetEqual(1,0,left$(Zkey$,len(ZKey$-2)+_
  1499.                              chr$(255)+chr$(255),Zrec$)
  1500.              'so get the last valid one
  1501.              stat = GetPrev(1,0,Zkey$,Zrec$)
  1502.              enum$ = right$(ZKey$,2)
  1503.              enum$ = right$(enum$,1)+left$(enum$,1)
  1504.              enum = cvi(enum$)       'make it an integer
  1505.              'inc the enumerator
  1506.              enum = enum + 1
  1507.              enum$ = mki$(enum)
  1508.              ZKey$ = NewKey$ + right$(enum$,1) + left$(enum$,1)
  1509.              stat = PutKey(1,0,ZKey$)
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.  
  1524.  
  1525.           20) QBTreeVer(ver)
  1526.  
  1527.           Return the version of the QBTREE access method (X100).
  1528.  
  1529.           ver            INTEGER.  Returned version number * 100.
  1530.  
  1531.           stat = QBTreeVer(ver)
  1532.           print "QBTREE version";ver\100
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.  
  1590.  
  1591.           21) StatDataFile(dfile,reclen,recs&,bfileno)
  1592.  
  1593.           Return information about the data file, dfile.
  1594.  
  1595.           dfile          INTEGER.  Number that was used as fileno in
  1596.                          OpenDataFile().
  1597.  
  1598.           reclen         INTEGER.  Returned length of records for dfile.
  1599.  
  1600.           recs&          LONG.     Returned number of records in dfile.
  1601.  
  1602.           bfileno        INTEGER.  Returned BASIC's file number for dfile.
  1603.  
  1604.           dfile = 0
  1605.           stat = StatDataFile(dfile,reclen,recs&,bfileno)
  1606.  
  1607.  
  1608.  
  1609.  
  1610.  
  1611.  
  1612.  
  1613.  
  1614.  
  1615.  
  1616.  
  1617.  
  1618.  
  1619.  
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.  
  1631.  
  1632.  
  1633.  
  1634.  
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.  
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.  
  1653.  
  1654.  
  1655.  
  1656.  
  1657.           22) StatKeyFile(kfile,keylen,keys&,bfileno)
  1658.  
  1659.           Return information about the key file, kfile.
  1660.  
  1661.           kfile          INTEGER.  Number that was used as fileno in
  1662.                          OpenKeyFile().
  1663.  
  1664.           keylen         INTEGER.  Returned length of keys for kfile.
  1665.  
  1666.           keys&          LONG.     Returned number of keys in kfile.
  1667.  
  1668.           bfileno        INTEGER.  Returned BASIC's file number for kfile.
  1669.  
  1670.           kfile = 0
  1671.           stat = StatKeyFile(kfile,keylen,keys&,bfileno)
  1672.  
  1673.  
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.  
  1680.  
  1681.  
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.           23) UpdateRecord(dfile,Qrec$)
  1724.  
  1725.           Overwrite the current data record in dfile with Qrec$. This
  1726.           allows you to update the contents of a record in a data file. Do
  1727.           not use this if you change an imbedded key in this record. If you
  1728.           want to change a key, first AddRecord() the new data and if a-ok,
  1729.           delete the old one (DeleteRecord()).
  1730.  
  1731.           dfile          INTEGER.  Number that was used as fileno in
  1732.                          OpenDataFile().
  1733.  
  1734.           Qrec$          STRING.   Data to use in replacing the previous
  1735.                          data in dfile.
  1736.  
  1737.           kfile = 0
  1738.           dfile = 0
  1739.           Qkey$ = acctid$
  1740.           stat = GetEqual(kfile,dfile,Qkey$,Qrec$)
  1741.           if stat = 0 then
  1742.              Qrec$ = newQrec$
  1743.              stat = UpdateRecord(dfile,Qrec$)
  1744.  
  1745.  
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751.  
  1752.  
  1753.  
  1754.  
  1755.  
  1756.  
  1757.  
  1758.  
  1759.  
  1760.  
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783.  
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.           24) LoadDataHeader(dfile)
  1790.  
  1791.           Load the header information for the data file, dfile, from       
  1792.           disk. This should be used in networking applications whenever   
  1793.           a file has been released to other processes.
  1794.  
  1795.           dfile          INTEGER.  Number that was used as fileno in
  1796.                          OpenDataFile().
  1797.  
  1798.           {See LoadKeyHeader() for an example.}
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835.  
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.  
  1842.  
  1843.  
  1844.  
  1845.  
  1846.  
  1847.  
  1848.  
  1849.  
  1850.  
  1851.  
  1852.  
  1853.  
  1854.  
  1855.           25) LoadKeyHeader(kfile)
  1856.  
  1857.           Load the header information for the key file, kfile, from disk.
  1858.           This should be used in networking applications whenever a file
  1859.           has been released to other processes. Note that internal pointers
  1860.           will probably have changed. A GetEqual() to the last processed
  1861.           record will need to be used followed by a GetNext() for
  1862.           sequential inorder processing.
  1863.  
  1864.           kfile          INTEGER.  Number that was used as fileno in 
  1865.                          OpenKeyFile().
  1866.  
  1867.           kfile = 0
  1868.           dfile = 0
  1869.           stat = LockKeyFile(kfile)
  1870.           if not stat then
  1871.              stat = LockDataHeader(dfile)
  1872.              if not stat then
  1873.                 stat = LockRecord(dfile,0&)
  1874.                 if not stat then
  1875.                    stat = LoadKeyHeader(kfile)
  1876.                    stat = LoadDataHeader(dfile)
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.  
  1888.  
  1889.  
  1890.  
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896.  
  1897.  
  1898.  
  1899.  
  1900.  
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906.  
  1907.  
  1908.  
  1909.  
  1910.  
  1911.  
  1912.  
  1913.  
  1914.  
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.  
  1921.           26) LockDataHeader(dfile)
  1922.  
  1923.           Lock the data header in dfile to the current process. Any other
  1924.           process requesting access to the header will be denied
  1925.           permission. This function should be used before adding or
  1926.           deleting a data record, though not needed for updating an
  1927.           existing record. To perform this DOS LAN function, the DOS
  1928.           program SHARE.EXE must be run.
  1929.  
  1930.           dfile          INTEGER.  Number that was used as fileno in
  1931.                          OpenDataFile().
  1932.  
  1933.           dfile = 0
  1934.           stat = LockDataHeader(dfile)
  1935.           if stat = 229 then
  1936.              print "Lock already in force"
  1937.           elseif stat = 232 then
  1938.              print "SHARE.EXE needs to be run"
  1939.  
  1940.  
  1941.  
  1942.  
  1943.  
  1944.  
  1945.  
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954.  
  1955.  
  1956.  
  1957.  
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.  
  1965.  
  1966.  
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.  
  1976.  
  1977.  
  1978.  
  1979.  
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.           27) LockKeyFile(kfile)
  1988.  
  1989.           Lock the key file, kfile, to the current process. Any other
  1990.           process requesting access to kfile will be denied permission. It
  1991.           is recommended that this be used, in LAN applications, prior to
  1992.           AddRecord(), PutKey(), DeleteKey(), DeleteRecord(). To perform
  1993.           this DOS LAN function, the DOS program SHARE.EXE needs to be run.
  1994.  
  1995.           kfile          INTEGER.  Number that was used as fileno in
  1996.                          OpenKeyFile().
  1997.  
  1998.           kfile = 0
  1999.           stat = LockKeyFile(kfile)
  2000.           if stat = 229 then
  2001.              print "Lock already in force"
  2002.           elseif stat = 232 then
  2003.              print "SHARE.EXE has not been run"
  2004.  
  2005.  
  2006.  
  2007.  
  2008.  
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014.  
  2015.  
  2016.  
  2017.  
  2018.  
  2019.  
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.  
  2028.  
  2029.  
  2030.  
  2031.  
  2032.  
  2033.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.  
  2042.  
  2043.  
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053.           28) LockRecord(dfile,recno&)
  2054.  
  2055.           Lock a specific record, recno&, in dfile, to the current process.
  2056.           Any other process requesting access to recno& will be denied
  2057.           permission. If recno&=0& then all records in dfile will be locked
  2058.           (records 1 to EOF plus). To perform this DOS LAN function, the
  2059.           DOS program SHARE.EXE must be run. Note that you must use
  2060.           LockDataHeader() to lock the header record.
  2061.  
  2062.           dfile          INTEGER.  Number that was used as fileno in
  2063.                          OpenDataFile().
  2064.  
  2065.           recno&         LONG.     Data record number in data file to lock.
  2066.  
  2067.           dfile = 0
  2068.           recno& = 1&        '{lock the first record in dfile}             
  2069.           stat = LockRecord(dfile,recno&)
  2070.           if stat = 229 then
  2071.              print "Lock already in force"
  2072.           elseif stat = 232 then
  2073.              print "SHARE.EXE needs to be run"
  2074.  
  2075.  
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.  
  2099.  
  2100.  
  2101.  
  2102.  
  2103.  
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117.  
  2118.  
  2119.           29) UnlockDataHeader(dfile)
  2120.  
  2121.           Unlock the data header in dfile. Commit the file header with a
  2122.           FlushDataFile() first. To perform this DOS LAN function, the DOS
  2123.           program SHARE.EXE must be installed.
  2124.  
  2125.           dfile          INTEGER.  Number that was used as fileno in 
  2126.                          OpenDataFile().
  2127.  
  2128.           dfile = 0
  2129.           stat = UnlockDataHeader(dfile)
  2130.           if stat = 229 then
  2131.              print "Lock already in force/cannot DUP LAN..."
  2132.            elseif stat = 232 then
  2133.              print "SHARE.EXE needs to be run"
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.  
  2162.  
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.  
  2171.  
  2172.  
  2173.  
  2174.  
  2175.  
  2176.  
  2177.  
  2178.  
  2179.  
  2180.  
  2181.  
  2182.  
  2183.  
  2184.  
  2185.           30) UnlockKeyFile(kfile)
  2186.  
  2187.           Unlock the key file, kfile. You should do this as soon as you
  2188.           have committed the file with FlushKeyFile() after a AddRecord(),
  2189.           PutKey(), DeleteKey(), DeleteRecord(). To perform this DOS LAN
  2190.           function, the DOS program SHARE.EXE needs to be run.
  2191.  
  2192.           kfile          INTEGER.  Number that was used as fileno in
  2193.                          OpenKeyFile().
  2194.  
  2195.           kfile = 0
  2196.           stat = UnlockKeyFile(kfile)
  2197.           if stat = 232 then
  2198.              print "SHARE.EXE has not been run"
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  
  2214.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.  
  2223.  
  2224.  
  2225.  
  2226.  
  2227.  
  2228.  
  2229.  
  2230.  
  2231.  
  2232.  
  2233.  
  2234.  
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240.  
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.           31) UnlockRecord(dfile,recno&)
  2252.  
  2253.           Unlock a specific record, recno&, in dfile. Once the record that
  2254.           was locked is no longer needed, you should unlock it. If a
  2255.           process terminates without releasing active locks on a file, the
  2256.           result is undefined. If recno&=0& then all records in dfile will
  2257.           be unlocked (records 1 to EOF plus). To perform this DOS LAN
  2258.           function, the DOS program SHARE.EXE must be installed.
  2259.  
  2260.           dfile          INTEGER.  Number that was used as fileno in
  2261.                          OpenDataFile().
  2262.  
  2263.           recno&         LONG.     Data record number in data file to
  2264.                          unlock.
  2265.  
  2266.           dfile = 0
  2267.           recno& = 1&        '{unlock the first record in dfile}           
  2268.           stat = UnlockRecord(dfile,recno&)
  2269.           if stat = 232 then
  2270.              print "SHARE.EXE has not been run"
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.  
  2278.  
  2279.  
  2280.  
  2281.  
  2282.  
  2283.  
  2284.  
  2285.  
  2286.  
  2287.  
  2288.  
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295.  
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.  
  2305.  
  2306.  
  2307.  
  2308.  
  2309.  
  2310.  
  2311.  
  2312.  
  2313.  
  2314.  
  2315.  
  2316.  
  2317.           ERROR CODES
  2318.  
  2319.  
  2320.           200  Key not found
  2321.                - the key is not in the index file. This will occur during a
  2322.                GetEqual(), DeleteKey(), DeleteRecord().
  2323.  
  2324.           201  Key already exists
  2325.                - duplicate keys are not allowed in QBTREE. This will occur
  2326.                during AddRecord(), PutKey(). If this error occurs with
  2327.                PutKey(), you must re-establish a valid data pointer before
  2328.                trying again.
  2329.  
  2330.           202  End of file
  2331.                - GetNext() has reached the end of file.
  2332.  
  2333.           203  Top of file
  2334.                - GetPrev() has reached the top of file.
  2335.  
  2336.           204  Empty file
  2337.                - there are no keys in the index file. This will occur when
  2338.                you attempt to perform functions that would require a non-
  2339.                empty file.
  2340.  
  2341.           205  Disk full
  2342.                - if the key file drive and the data file drive are the same
  2343.                a minimum of 2 clusters are needed for the key file plus the
  2344.                clusters required to completely hold the data record before
  2345.                you can AddRecord() or PutKey(). If they're separate drives,
  2346.                the key file needs at least 2 clusters free on its disk and
  2347.                the data file disk as many clusters as needed to hold the
  2348.                data record. This will also occur during CreateKeyFile(),
  2349.                CreateDataFile().
  2350.  
  2351.           206  Data pointer invalid
  2352.                - a valid QBTREE key access, either GetEqual(), GetNext(),
  2353.                GetPrev(), GetFirst(), GetLast() must occur right before a
  2354.                data record can be UpdateRecord() or a key can be PutKey().
  2355.  
  2356.           207-209  reserved
  2357.  
  2358.           210  Stack overflow (10 levels)
  2359.                - the internal tracking stack exceeded capacity. This should
  2360.                never occur.
  2361.  
  2362.           211  Function not implemented
  2363.                - this won't happen unless you call the low-level driver.
  2364.  
  2365.           212-218  reserved
  2366.  
  2367.           219  File number invalid
  2368.                - the file number for the keyfile or datafile is greater
  2369.                than the highest allocated in BTREE45.BAS. Increase the
  2370.                MKF/MDF maximum files constant in the interface source.
  2371.  
  2372.  
  2373.  
  2374.  
  2375.  
  2376.  
  2377.  
  2378.  
  2379.  
  2380.  
  2381.  
  2382.  
  2383.  
  2384.           220  Data record length invalid
  2385.                - length must be from 3-32767 bytes when creating data file.
  2386.  
  2387.           221  Key length invalid
  2388.                - length must be from 1-64 bytes when creating key file.
  2389.  
  2390.           222  File not open
  2391.                - the fileno for a key or data file operation is not opened.
  2392.  
  2393.           223  Invalid null key assignment
  2394.                -a null key cannot be used. Null is defined in QBTREE as
  2395.                either ASCII 0 or ASCII 255. This will occur in AddRecord(),
  2396.                Delete(), GetEqual(), PutKey(). This pertains only to the
  2397.                first character of the key. This will also occur if you
  2398.                reach top of file and attempt to Delete().
  2399.  
  2400.           224  Invalid record number
  2401.                - a record number less than 1 was used in GetDirect(). Upper
  2402.                bounds is not validated.
  2403.  
  2404.           225  No handle available for DUP
  2405.                - no DOS handles are available to flush files. Use a greater
  2406.                value in config.sys FILES= (FILES=20).
  2407.  
  2408.           226  Invalid drive specifier
  2409.                - the drive specified in CreateKeyFile(), CreateDataFile()
  2410.                is not a valid DOS drive.
  2411.  
  2412.           227  reserved
  2413.  
  2414.           228  File not QBTREE
  2415.                - the filename in OpenKeyFile() or OpenDataFile() is not
  2416.                recognized as a QBTREE file.
  2417.  
  2418.           229  Lock already in force
  2419.                - the lock requested cannot be made because an existing lock
  2420.                of the header, record or file is in force. See FlushFile().
  2421.  
  2422.           230  File already exists
  2423.                - the CreateKeyFile() or CreateDataFile() filename already
  2424.                exists. Delete the filename if you really want to use the
  2425.                same filename.
  2426.  
  2427.           231  File not found
  2428.                - the filename$ specified in OpenKeyFile() or OpenDataFile()
  2429.                does not exist or is not valid.
  2430.  
  2431.           232  General lock failure
  2432.                - usually means that SHARE.EXE was not run before using the
  2433.                network functions.
  2434.  
  2435.           233-255  reserved
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446.  
  2447.  
  2448.  
  2449.           TECHNICAL SPECIFICATIONS 
  2450.  
  2451.  
  2452.           Key length     : 1-64 bytes (ASCII sort), constant
  2453.           Record length  : 3-32767 bytes, constant (available near memory)
  2454.           Node size      : 512 bytes
  2455.           Keys per node  : 7-84 keys, (512-3)\(key length+5)
  2456.           Max keys/file  : 5.5 million keys (65535 nodes)
  2457.           Max datafile   : 16 million bytes
  2458.           Max key files  : 5 opened at one time (* to 255 total w/source)
  2459.           Max data files : 5 opened at one time (* and DOS 3.30 and up)
  2460.  
  2461.  
  2462.           Key file header format (first sector (512 bytes) of key file):
  2463.  
  2464.           filetype        char    ;  0 file type, "*", ASCII 42
  2465.           rootnode        int     ;  1 sector in file of root node
  2466.           nokeyslo        int     ;  3 number of keys (low word)
  2467.           nokeyshi        byte    ;  5 number of keys (high byte)
  2468.           keyavsec        int     ;  6 key available list head
  2469.           nxkeysec        int     ;  8 next free sector
  2470.           keylen          byte    ; 10 length of key
  2471.           maxkeys         byte    ; 11 maximum keys per node
  2472.           ackysc          int     ; 12 actual key sector in buffer
  2473.           cukysc          int     ; 14 current key sector
  2474.           cukyof          byte    ; 16 current key offset
  2475.           iflag           byte    ; 17 internal flag
  2476.           stkcnt          byte    ; 18 tree level count
  2477.           pstack          long    ; 19 - 58 tree stack (4 bytes per level)
  2478.           reserved        any     ; 59 - 255
  2479.           free use        any     ; 256 - 383
  2480.           reserved        any     ; 384 - 511
  2481.  
  2482.  
  2483.           Data file header format (first 32 bytes of data file):
  2484.  
  2485.           filetype        char    ;  0 file type, "S"
  2486.           reclen          int     ;  1 length of record
  2487.           norecslo        int     ;  3 number of records (low word)
  2488.           norecshi        byte    ;  5 number of records (high byte)
  2489.           datavlo         int     ;  6 data available list (low word)
  2490.           datavhi         byte    ;  8 data available list (high byte)
  2491.           nxdalo          int     ;  9 next data record avail (low word)
  2492.           nxdahi          byte    ; 11 next data record avail (high byte)
  2493.           internal        byte    ; 12 internal flag
  2494.           cudalo          int     ; 13 current data record (low word)
  2495.           cudahi          byte    ; 15 current data record (high byte)
  2496.           internal        any     ; 16 - 31 reserved
  2497.  
  2498.  
  2499.  
  2500.  
  2501.  
  2502.  
  2503.  
  2504.  
  2505.  
  2506.  
  2507.  
  2508.  
  2509.  
  2510.  
  2511.  
  2512.  
  2513.  
  2514.  
  2515.           There is an internal first key with a null value immediately
  2516.           following the key header.
  2517.  
  2518.           Beginning each node (sector) is a count key byte. This is the
  2519.           count of keys on that sector. Then for each key is a 16-bit
  2520.           previous node pointer, the key itself, the 24-bit data pointer
  2521.           for that key, and a 16-bit next node pointer (node pointers are
  2522.           zero at the leaf nodes).
  2523.  
  2524.           02  00 00  000000  00 00 00  00 00  KEY001  01 00 00  00 00 ... 
  2525.            1.  2.    3.      4.      5.    6.      7.     8.   9.
  2526.  
  2527.           1. Key count for that node
  2528.           2. Node back pointer (for non-leaf nodes)
  2529.           3. The internal null key (in least-valued node)
  2530.           4. The 24-bit data record pointer (LB/HB/XB)
  2531.           5. Forward ptr/back ptr (for non-leaf nodes)
  2532.           6. First logical key
  2533.           7. Its data pointer (record number in data file)
  2534.           8. Its forward pointer (for non-leaf nodes)
  2535.           9. repeat 3 to 8 for each key on node
  2536.  
  2537.  
  2538.           QBTREE makes some allowances on the strict B-TREE and ISAM
  2539.           definitions. For all practical purposes, consider QBTREE superior
  2540.           to the text-book implementations of these.
  2541.  
  2542.  
  2543.           Data record format:
  2544.  
  2545.           Straight data after the header. Logical record #1 follows the
  2546.           header. Records that have been deleted have the first 3 bytes
  2547.           used as a link to the records available list. datavlo/hi in the
  2548.           header point to the last deleted record (or 0 if none). The first
  2549.           3 bytes of that deleted record point to the previously deleted
  2550.           record, and so on. When 3 zero bytes form the pointer, that
  2551.           record is the last in the list of deletes. Any additional records
  2552.           then will expand the file.
  2553.  
  2554.           By reserving the first 3 bytes of the data record it would be
  2555.           easy to reindex a datafile. Set the bytes to all ASCII 255. You
  2556.           then use GetDirect(), check to see if the 3 bytes are still 255s,
  2557.           and if so, AddRecord() to a new key and data file. If not 255s,
  2558.           you know that that record is deleted.
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.  
  2570.  
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.  
  2581.           COMPILER INFORMATION and RESOURCE ALLOCATION
  2582.  
  2583.           BTREE45.BAS, the I/O and interface portion of QBTREE, was written 
  2584.           and compiled with QuickBASIC 4.00b. The BTREE45.BAS file was
  2585.           compiled with the /O option only. If using QuickBASIC 4.00b+,
  2586.           which has a better error handling algorithm than 4.0, you can
  2587.           trap I/O errors with QB even though the BTREE45 module was
  2588.           compiled without the /E or /X options. However, version 4.00 will
  2589.           dump the program to DOS on errors. So if your are using version
  2590.           4.00, you need to perform common I/O checks for fatal errors such
  2591.           as checking to see that the drive is ready etc., before using
  2592.           QBTREE functions with QB/BC 4.0.
  2593.  
  2594.           Storage for the data buffers and headers are allocated in the    
  2595.           default data area of QB. BTREE45.BAS storage allocation is      
  2596.           as follows (with default MKF and MKD = 4):
  2597.  
  2598.           2 integer arrays (0 to 4) for file handles.
  2599.           1 key hdr array (0 to 4) for key file headers, ea 62 bytes.
  2600.           1 data hdr array (0 to 4) for data file headers, ea 32 bytes.
  2601.           1 key node array (0 to 4) for node buffers, ea 512 bytes.
  2602.           1 data buffer array$ (0 to 4) for data record I/O, size allocated
  2603.             is equal to that dfile's record length (var-len$).
  2604.           1 long integer array (0 to 4) to track current record numbers.
  2605.           2 integer arrays (0 to 4) to track file drives.
  2606.           1 type variable for interfacing with QBTREE low-level, 20 bytes. 
  2607.           ... and other miscellaneous variables (see the source for more)
  2608.  
  2609.  
  2610.  
  2611.  
  2612.  
  2613.  
  2614.  
  2615.  
  2616.  
  2617.  
  2618.  
  2619.  
  2620.  
  2621.  
  2622.  
  2623.  
  2624.  
  2625.  
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639.  
  2640.  
  2641.  
  2642.  
  2643.  
  2644.  
  2645.  
  2646.  
  2647.           USING TYPED VARIABLES
  2648.  
  2649.  
  2650.           QBTREE uses a simple variable, namely a var-len string, to get
  2651.           and put data in the data file. To use QB TYPEd variables, you may
  2652.           want to use this method. Setup your TYPEd variable, then allocate
  2653.           enough space in a var-len string to copy to and from it.
  2654.  
  2655.           TYPE dataTYPE
  2656.            TAG AS STRING * 4
  2657.            SSN AS STRING * 9
  2658.            AGE AS INTEGER
  2659.            XXX AS STRING * 1
  2660.           END TYPE '16
  2661.  
  2662.           DIM SSNage AS dataTYPE
  2663.  
  2664.           SSNage.TAG = ""
  2665.           SSNage.SSN = ssn$               
  2666.           SSNage.AGE = age    
  2667.  
  2668.           DIM SHARED work$
  2669.           work$ = SPACE$(LEN(SSNage))
  2670.  
  2671.           FromSec = VARSEG(SSNage)
  2672.           FromOff = VARPTR(SSNage)
  2673.           ToSec = VARSEG(work$)     '{we want the offset to the string's}
  2674.           ToOff = SADD(work$)       '{address, not the string descriptor's}
  2675.           count = len(work$)
  2676.           dir = 1
  2677.           MemCopy FromSec,FromOff,ToSec,ToOff,count,dir
  2678.  
  2679.           '{You now have the TYPEd variable data in a var-len string that} 
  2680.           '{can be used as the Qrec$. To put Qrec$ in the typed variable,} 
  2681.           '{reverse the From/To assignments.}
  2682.  
  2683.           {MemCopy is included in the QBTREE45.LIB and QBTREE45.BI}
  2684.  
  2685.  
  2686.  
  2687.  
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693.  
  2694.  
  2695.  
  2696.  
  2697.  
  2698.  
  2699.  
  2700.  
  2701.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.           NON-UNIQUE KEYS
  2714.  
  2715.  
  2716.           QBTREE doesn't allow duplicate keys (this may be an inconvenience
  2717.           in some data base programming) but this can easily be worked
  2718.           around by adding to each key an additional two bytes. These bytes
  2719.           would act to differentiate up to 65536 'identical' keys.
  2720.  
  2721.           For example, if the needed key length is 16 bytes, make it 18.
  2722.           Reserve bytes 17 and 18 so that you can enumerate identical keys.
  2723.           When adding a key that doesn't already exist, set bytes 17 and 18
  2724.           to ASCII 0. If the key already exists (error 201), use the
  2725.           highest possible enumerator (ASCII 255,255) for the key. Do a
  2726.           GetEqual(). Since that key will not be found (error 200), do a
  2727.           GetPrev(). This retrieves the very last inorder record for the
  2728.           key. Add 1 to the found enumerator value and use that as the
  2729.           enumerator for the next key. Add the key.
  2730.  
  2731.           Note: For proper sorting, you should have the most significant
  2732.           byte of the enumerator first and the least significant last. See
  2733.           the PutKey() code example for more.
  2734.                  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.  
  2752.  
  2753.  
  2754.  
  2755.  
  2756.  
  2757.  
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763.  
  2764.  
  2765.  
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.  
  2779.           PDS QBX ENVIRONMENT
  2780.  
  2781.  
  2782.           QBX, the PDS 7 environment, uses far strings exclusively. QBTREE
  2783.           works with strings that are known to be in the default data area
  2784.           DGROUP. Because of this, QBTREE is not compatible with the QBX
  2785.           environment. It is compatible with the PDS BC when far strings
  2786.           are not used.
  2787.  
  2788.           With the BTREE45.BAS source, a skilled programmer could simulate
  2789.           the data structures needed in DGROUP (using COMMON, or writing a
  2790.           routine to allocate data from the stack). Once that's done,
  2791.           QBTREE could be used in the QBX environment.
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835.  
  2836.  
  2837.  
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.  
  2844.  
  2845.           ****************** QBTREE REGISTRATION FORM ********** 450 ***
  2846.  
  2847.           Name of registrant: __________________________________________
  2848.  
  2849.           Amount paid: $ ____________ ($45 ea.)   If you want me to send 
  2850.                                                   the interface source
  2851.                                                   code, fill out the non-
  2852.                                                   release form below.
  2853.  
  2854.           Comments: ___________________________________________________
  2855.  
  2856.           _____________________________________________________________
  2857.  
  2858.           Contact:   ________________________ Phone:(   )____-__________
  2859.  
  2860.           Would you like to be added to our mailing list? ______________
  2861.  
  2862.           Mail to:   ___________________________________________________
  2863.  
  2864.           ______________________________________________________________
  2865.  
  2866.           ______________________________________________________________
  2867.  
  2868.           Send this page with payment to:
  2869.  
  2870.                Cornel Huth
  2871.                ATTN: QBTREE 4.50 REGISTRATION
  2872.                6402 Ingram Rd.
  2873.                San Antonio, TX  78238
  2874.  
  2875.  
  2876.           *** NON-RELEASE FORM for QBTREE 4.50 INTERFACE SOURCE CODE ****
  2877.  
  2878.           I, _______________________________________, hereby agree not
  2879.  
  2880.           to distribute, nor claim ownership of, QBTREE source code, or
  2881.  
  2882.           any modification to the QBTREE interface, and not remove the
  2883.  
  2884.           copyright notice of Cornel Huth from any part of QBTREE.
  2885.  
  2886.  
  2887.           DATE:__________________
  2888.  
  2889.  
  2890.           _______________________
  2891.  
  2892.  
  2893.           (If you would like the interface source code in QB 4.00+,        
  2894.           print your name in the first blank, date the second, and        
  2895.           sign the third.)
  2896.  
  2897.  
  2898.  
  2899.  
  2900.  
  2901.  
  2902.  
  2903.  
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.  
  2910.  
  2911.  
  2912.  
  2913.  
  2914.  
  2915.  
  2916.  
  2917.  
  2918.  
  2919.  
  2920.  
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.  
  2929.  
  2930.  
  2931.  
  2932.  
  2933.  
  2934.  
  2935.  
  2936.  
  2937.  
  2938.  
  2939.  
  2940.  
  2941.  
  2942.  
  2943.  
  2944.  
  2945.  
  2946.  
  2947.  
  2948.  
  2949.  
  2950.  
  2951.  
  2952.  
  2953.  
  2954.  
  2955.  
  2956.  
  2957.  
  2958.  
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964.  
  2965.  
  2966.  
  2967.  
  2968.  
  2969.  
  2970.  
  2971.